package com.aracky.system.service.impl;

import com.aracky.common.exception.BaseException;
import com.aracky.common.util.ComUtil;
import com.aracky.common.util.ConvertUtil;
import com.aracky.system.constants.ComConstants;
import com.aracky.system.mapper.SysRoleMenuMapper;
import com.aracky.system.model.entity.SysBtnConfig;
import com.aracky.system.model.entity.SysMenuTable;
import com.aracky.system.model.entity.SysRoleMenu;
import com.aracky.system.model.vo.SysBtnConfigVO;
import com.aracky.system.model.vo.SysMenuTableVO;
import com.aracky.system.model.vo.SysMenuVO;
import com.aracky.system.model.vo.view.MenuVO;
import com.aracky.system.model.vo.view.MetaVO;
import com.aracky.system.service.SysBtnConfigService;
import com.aracky.system.service.SysMenuTableService;
import com.aracky.system.service.SysRoleMenuService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色和菜单关联表 服务实现类
 * </p>
 *
 * @author zzp
 * @since 2022-07-15 03:52:55
 */
@Service
public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRoleMenu> implements SysRoleMenuService {

    @Autowired
    private SysMenuTableService sysMenuTableService;

    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Autowired
    private SysBtnConfigService sysBtnConfigService;

    @Override
    public List<MenuVO> getCurrentMenuList(Long currentUserId, boolean needBuildTree) {
        List<SysMenuVO> currentMenuList = sysRoleMenuMapper.findCurrentMenuList(currentUserId);

        if (currentMenuList == null || currentMenuList.isEmpty()) {
            throw new BaseException("当前用户未设置菜单");
        }
        if (!needBuildTree) {
            return ConvertUtil.sourceToTargets(currentMenuList,MenuVO.class);
        }
        //筛选按钮
        currentMenuList = currentMenuList.stream()
                .filter(sysMenuVO ->
                        !ComConstants.MENU.TYPES[2].equals(sysMenuVO.getMenuType())).collect(Collectors.toList());
        List<MenuVO> menuList = buildMenuVoList(currentMenuList);

        //分组构造树结构
        Map<Long, List<MenuVO>> groupMap = menuList.stream().collect(Collectors.groupingBy(MenuVO::getParentId));
        List<MenuVO> menuVOList = groupMap.get(0L);
        recursionMenu(menuVOList, groupMap);
        return menuVOList;
    }

    /**
     * 递归设置子菜单数据
     *
     * @param childrenMenu
     * @param groupMap
     */
    private void recursionMenu(List<MenuVO> childrenMenu, Map<Long, List<MenuVO>> groupMap) {
        if (ComUtil.isNullList(childrenMenu)) {
            return;
        }
        childrenMenu.forEach(item -> {
            List<MenuVO> menuVOList = groupMap.get(item.getMenuId());
            recursionMenu(menuVOList, groupMap);
            item.setChildren(menuVOList);
        });
    }


    /**
     * 构造数据
     *
     * @param currentMenuList
     * @return
     */
    private List<MenuVO> buildMenuVoList(List<SysMenuVO> currentMenuList) {

        //提取菜单id
        List<Long> menuIdList = currentMenuList.stream()
                .map(SysMenuVO::getMenuId).collect(Collectors.toList());

        //查询当前菜单下的所以配置信息
        LambdaQueryWrapper<SysMenuTable> tableLambdaQueryWrapper =
                Wrappers.<SysMenuTable>lambdaQuery().in(SysMenuTable::getMenuId, menuIdList);
        List<SysMenuTable> sysMenuTableList = sysMenuTableService.list(tableLambdaQueryWrapper);
        List<SysMenuTableVO> sysMenuTableVOList = ConvertUtil.sourceToTargets(sysMenuTableList, SysMenuTableVO.class);
        Map<Long, List<SysMenuTableVO>> sysMenuTableMap = sysMenuTableVOList.stream().collect(Collectors.groupingBy(SysMenuTableVO::getMenuId));

        //查询所有按钮配置信息
        List<SysBtnConfigVO> sysBtnConfigVOList = sysBtnConfigService.getBtnCongifList(menuIdList);
        Map<Long, List<SysBtnConfigVO>> sysBtnConfigMap = sysBtnConfigVOList.stream().collect(Collectors.groupingBy(SysBtnConfigVO::getParentId));

        //返回数据
        return loopCurrentMenuList(currentMenuList, sysMenuTableMap, sysBtnConfigMap);
    }

    /**
     * 设置数据值信息
     *
     * @param currentMenuList
     * @param sysMenuTableMap
     * @param sysBtnConfigMap
     */
    private List<MenuVO> loopCurrentMenuList(List<SysMenuVO> currentMenuList, Map<Long, List<SysMenuTableVO>> sysMenuTableMap,
                                             Map<Long, List<SysBtnConfigVO>> sysBtnConfigMap) {
        //构造数据信息
        List<MenuVO> menuList = new ArrayList<>(currentMenuList.size());
        MenuVO menuVO;
        MetaVO metaVO;
        for (SysMenuVO sysMenuVO : currentMenuList) {

            menuVO = new MenuVO();
            menuVO.setMenuId(sysMenuVO.getMenuId());
            menuVO.setParentId(sysMenuVO.getParentId());
            menuVO.setAlwaysShow(Boolean.TRUE);
            String component = sysMenuVO.getParentId() == 0L ? ComConstants.MENU.COMPONENT : sysMenuVO.getComponent();
            menuVO.setComponent(component);
            menuVO.setHidden(!sysMenuVO.getVisible());
            menuVO.setName(sysMenuVO.getName());
            menuVO.setPath(sysMenuVO.getUrl());
            menuVO.setPerms(sysMenuVO.getPerms());
            menuVO.setMenuType(sysMenuVO.getMenuType());

            //构造meta对象
            metaVO = new MetaVO();
            metaVO.setTitle(sysMenuVO.getMenuName());
            metaVO.setIcon(sysMenuVO.getIcon());
            metaVO.setNoCache(sysMenuVO.getIsRefresh());
            String link = ComConstants.MENU.TARGET[1].equals(sysMenuVO.getTarget()) ? sysMenuVO.getUrl() : null;
            metaVO.setLink(link);
            //按钮配置
            List<SysBtnConfigVO> btnConfigVOList = sysBtnConfigMap.get(sysMenuVO.getMenuId());
            metaVO.setBtnConfig(btnConfigVOList);
            //菜单模型配置
            List<SysMenuTableVO> menuTableVOList = sysMenuTableMap.get(sysMenuVO.getMenuId());
            metaVO.setPageConfig(menuTableVOList);

            menuVO.setMeta(metaVO);

            menuList.add(menuVO);
        }
        return menuList;
    }
}
